home *** CD-ROM | disk | FTP | other *** search
- /*
-
- MercuryFilter Version 1.00a for All MS-DOS Machines
- Copyright (c) 1995 Delmonta all rights reserved.
-
- コンパイルについて:
- 浮動小数点演算は使用していませんので、printf関数は
- doubleに対応していないサブセット版を使用してもかまいません。
- */
-
- #include<ctype.h>
- #include<jstring.h>
- #include<stdarg.h>
- #include<stdio.h>
- #include<stdlib.h>
- #include<string.h>
-
- /*****************************************************************************/
- /* 下請けルーチン */
- /*****************************************************************************/
- #define MEMBERSOF(array) (sizeof(array)/sizeof((array)[0]))
-
- static char Separators[] = " \t\n\v";
- static int Linepos = 0;
- /*--------------------------------エラー終了---------------------------------*/
- static void die(char *s,...)
- {
- va_list ap;
-
- fprintf(stderr,"%d:",Linepos);
-
- va_start(ap,s);
- vfprintf(stderr,s,ap);
- va_end(ap);
-
- exit(1);
- }
- /*--------------------文字列の両端の空白類をカットする-----------------------*/
- static char *chop(char *s)
- {
- while (isspace(*s))
- s++;
-
- if (*s!='\0')
- {
- char *p = strchr(s,'\0');
-
- while (isspace(*--p))
- ;
-
- *(p+1) = '\0';
- }
-
- return s;
- }
- /*-------------------エラー処理を含む文字列の二重化--------------------------*/
- static char *xstrdup(char *s)
- {
- s = strdup(s);
- if (s!=NULL)
- return s;
-
- die("メモリ不足です\n");
- exit(1);
- }
- /*****************************************************************************/
- /* 各キーワードの処理 */
- /*---------------------------------------------------------------------------*/
- /* 各キーワードを処理する関数が0を返した場合、その行は出力されない */
- /*****************************************************************************/
- static int Keywordnum = 0;
- static int Groupkey_num = 0;
-
- static char *Keyword[32];
-
- static struct
- {
- char *name;
- int keywordid;
- } Groupkey[256];
- /*------------キーワードテーブルから指定されたキーワードを探す---------------*/
- /* 見つからなければエラー終了する。 */
- /*---------------------------------------------------------------------------*/
- static int find_keyword(char *p)
- {
- int i;
-
- for (i=0 ; i<Keywordnum ; i++)
- {
- if (stricmp(p,Keyword[i])==0)
- return i;
- }
-
- die("キーワード %s は定義されていません\n",p);
- exit(1);
- }
- /*----------------グループキーテーブルからグループキーを探す-----------------*/
- /* 見つからなければ黙って-1を返す。 */
- /* 返すのは、配列Groupkeyの添え字ではなく、対応するKEYWORDの番号。 */
- /*---------------------------------------------------------------------------*/
- static int find_groupkey(char *p)
- {
- int i;
-
- for (i=0 ; i<Groupkey_num ; i++)
- {
- if (stricmp(p,Groupkey[i].name)==0)
- return Groupkey[i].keywordid;
- }
-
- return -1;
- }
- /*--------------------------KEYWORD(1);PROGRAM以前---------------------------*/
- static int cmd_keyword_def(char *dst,char *src)
- {
- char *p;
-
-
- *dst = '\0';
-
- for (p=jstrtok(src,Separators);p!=NULL;p=jstrtok(NULL,Separators))
- {
- Keyword[Keywordnum++] = xstrdup(p);
- strcat(dst,p);
- strcat(dst," ");
- }
-
- return 1;
- }
- /*-------------------------KEYWORD(2);PROGRAM以後----------------------------*/
- static int cmd_keyword_ref(char *dst,char *src)
- {
- char *p;
-
- *dst = '\0';
-
- for (p=jstrtok(src,Separators);p!=NULL;p=jstrtok(NULL,Separators))
- {
- int n;
-
- n = find_groupkey(p);
- if (n>=0)
- p = Keyword[n];
- else
- find_keyword(p);
-
- strcat(dst,p);
- strcat(dst," ");
- }
-
- return 1;
- }
- /*---------------------------------GROUP-------------------------------------*/
- static int cmd_group(char *dst,char *src)
- {
- char *p;
- int id;
-
- p = jstrtok(src,Separators);
- if (p==NULL)
- return 0;
-
- id = find_keyword(p);
- while ((p=jstrtok(NULL,Separators))!=NULL)
- {
- if (Groupkey_num==MEMBERSOF(Groupkey))
- die("グループキーの数が多すぎます\n");
-
- if (find_groupkey(p)>=0)
- die("グループキー%sが二重に定義されています\n",p);
-
- Groupkey[Groupkey_num].name = xstrdup(p);
- Groupkey[Groupkey_num].keywordid = id;
-
- Groupkey_num++;
- }
- return 0;
- }
- /*****************************************************************************/
- /* メインプログラム */
- /*****************************************************************************/
- #define KEYWORD_DEF 0
- #define KEYWORD_REF 1
- #define GROUP 2
-
- #define THROUGH 3
- #define CUT 4
-
- static int (*Command[3])(char *dst,char *src) =
- {cmd_keyword_def,cmd_keyword_ref,cmd_group};
- /*-----------------------------コマンド名の解析------------------------------*/
- static int getcommandid(char *s)
- {
- static int isafterprogram = 0;
-
- static int cutnum = 0; /* 削除するキーワードの数 */
- static int throughnum = 6; /* 素通しするキーワードの数 */
-
- static char *cuttable[256]; /* 削除するキーワード */
- static char *throughtable[256] = /* 素通しするキーワード */
- {"DRIVE","MAKE","DIR","README","MANUAL","COPY"};
-
- int i;
-
- strupr(s);
-
- if (stricmp(s,"KEYWORD")==0)
- {
- if (isafterprogram)
- return KEYWORD_REF;
- else
- return KEYWORD_DEF;
- }
- else if (stricmp(s,"GROUP")==0)
- return GROUP;
- else if (stricmp(s,"PROGRAM")==0)
- {
- isafterprogram = 1;
- return THROUGH;
- }
-
- for (i=0 ; i<cutnum ; i++)
- {
- if (stricmp(s,cuttable[i])==0)
- return CUT;
- }
-
- for (i=0 ; i<throughnum ; i++)
- {
- if (stricmp(s,throughtable[i])==0)
- return THROUGH;
- }
-
- rep:
- fprintf(stderr, "未定義のコマンドです %s\n"
- "中止<A>,素通し<T>,削除<C>?",s);
-
- i = getche();
- putc('\n',stderr);
-
- switch (i)
- {
- case 'A':
- case 'a':
- exit(1);
- case 'T':
- case 't':
- if (throughnum == MEMBERSOF(throughtable))
- die("THROUGHキーワードの数が多すぎます\n");
- throughtable[throughnum++] = xstrdup(s);
- return THROUGH;
- case 'C':
- case 'c':
- if (cutnum==MEMBERSOF(cuttable))
- die("CUTキーワードの数が多すぎます\n");
- cuttable[cutnum++] = xstrdup(s);
- return CUT;
- default:
- goto rep;
- }
- }
- /*-----------------------------オプションの解析------------------------------*/
- static void option(char *s)
- {
- switch (s[1])
- {
- case 'H':
- case 'h': /* ヘルプは、明示的にオプションを指定して出力する */
- case '?': /* ものだから、出力先はstdoutにする */
- printf("MCFILTER ファイル名\n\n");
- break;
- default:
- die("不正なオプションです %s\n",s);
- }
- }
- /*------------------------------メインルーチン-------------------------------*/
- extern int main(int argc,char **argv)
- {
- FILE *fpi;
-
- char buf[2][512];
-
- #define fpo stdout
-
- while (++argv,--argc)
- {
- if (**argv=='-')
- {
- option(*argv);
- continue;
- }
-
- if ((fpi=fopen(*argv,"r"))==NULL)
- {
- fprintf(stderr,"%sがオープンできません\n",*argv);
- exit(1);
- }
-
- Linepos = 0;
-
- while (fgets(buf[0],sizeof(buf[0]),fpi)!=NULL)
- {
- char *p,*q;
- int id;
-
- Linepos++;
-
- p = chop(buf[0]);
- if (*p=='\0' || *p=='#') /* 空行・コメント行の削除 */
- continue;
-
- q = strchr(p,':');
- if (q==NULL)
- die("不正な行です %s\n",p);
-
- *q = '\0';
- p = chop(p);
- q = chop(q+1);
-
- id = getcommandid(p);
- if (id==CUT)
- continue;
- else if (id!=THROUGH)
- {
- if (!Command[id](buf[1],q))
- continue;
-
- q = buf[1];
- }
-
- fprintf(fpo,"%s:%s\n",p,q);
- }
-
- fclose(fpi);
- }
-
- return 0;
- }
- /*----------------------------End of MCFILTER.C------------------------------*/